package com.d.business.controller;

import java.lang.reflect.Method;
import java.util.*;

import com.d.business.domain.DingProcessRecordsDO;
import com.d.business.domain.dto.BDingTalkDTO;
import com.d.business.service.BDingTalkService;
import com.d.business.service.DingProcessRecordsService;
import com.d.client.YidaClient;
import com.d.client.dto.YidaOperationRecordsResultDTO;
import com.d.client.dto.YidaProcessInstanceInfosResultDTO;
import com.d.ding.DingApproveService;
import com.d.ding.constants.DingFromConstants;
import com.d.ydfactory.constants.ApproveConstant;
import com.d.common.utils.RT;
import com.d.common.utils.RedisUtil;
import com.d.ydfactory.YdApproveFactory;
import com.d.ydfactory.handle.ApproveEventHandle;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


/**
 * 钉钉审批流程记录表
 *
 * @author wang
 * @email wangfst@foxmail.com
 * @date 2024-03-13 16:48:25
 */

@Controller
@RequestMapping("/api/dingProcessRecords")
public class DingProcessRecordsController {

    private static final Logger logger = LoggerFactory.getLogger(DingProcessRecordsController.class);

    @Autowired
    private DingProcessRecordsService dingProcessRecordsService;

    @Autowired
    private YidaClient yidaClient;

//    @Autowired
//    private RpcPurchaseOrderConsumerPhp rpcPurchaseOrderConsumerPhp;
//    @Autowired
//    private RpcPaymentConsumerPhp rpcPaymentConsumerPhp;
//
//    @Autowired
//    private BAdminInfoService bAdminInfoService;
//
//    @Autowired
//    private BPurchaseOrderConsumer bPurchaseOrderConsumer;

    @Autowired
    private ApproveEventHandle approveEventHandle;

    private final String processRedisKey = "YD_PROCESS_NODE:";

    /**
     * 宜搭审批回调
     *
     * @param businessNo
     * @param instanceId node first部门审核 last财务审核  如果node不等于null 则只修改node
     * @return
     */
    @ResponseBody
    @GetMapping("/ydcallback")
    public RT ydcallback(String businessNo, String instanceId, String formUuid, String node) {
        try {
//            logger.info("------------------aaaaaaaaaaaaabusinessNo："+businessNo+"aaaaaaaaaformUuid:"+formUuid+"aaaaaaaaaaaainstanceId:"+instanceId);
            //如果node不等于空则为流程内调用的，将node存到redis中，流程结束则删除
            if (node != null && !"".equals(node)) {
                RedisUtil.setJedisVal(processRedisKey + formUuid + ":" + instanceId + "_" + businessNo, node);
                return RT.ok();
            }

            Integer processType = ApproveConstant.yidaProcessConfMap.get(formUuid);
            if (processType == null)
                return RT.ok();

//            logger.info("---------processType:"+processType+"---------BBBBBBBBBBBBBBBBBbusinessNo："+businessNo+"aaaaaaaaaformUuid:"+formUuid+"aaaaaaaaaaaainstanceId:"+instanceId);

            DingProcessRecordsDO startRecord = dingProcessRecordsService.getByBusindssNoAndTypeAndStatus(businessNo, processType, "START");
            if (startRecord == null)
                return RT.error();
            YidaProcessInstanceInfosResultDTO resultDTO = yidaClient.instancesInfos(instanceId, ApproveConstant.YIDA_APP_CODE, ApproveConstant.YIDA_APP_SECRET, startRecord.getStaffId());
//        if (resultDTO == null) {
//            String callbackParamsStr = businessNo+"_"+instanceId+"_"+formUuid+"_"+node;
//
//        }

            YidaOperationRecordsResultDTO recordsResultDTO = yidaClient.operationRecords(instanceId, ApproveConstant.YIDA_APP_CODE, ApproveConstant.YIDA_APP_SECRET, startRecord.getStaffId());
            YidaOperationRecordsResultDTO.ResultBean result = this.lastRecords(recordsResultDTO);//
            String staffId = result.getOperatorUserId();
            String remark = result.getRemark();

            DingProcessRecordsDO dingR = new DingProcessRecordsDO();
            dingR.setInstanceId(instanceId);
            dingR.setCreatedTime(new Date());
            dingR.setFinishTime(new Date());
            dingR.setBusinessNo(businessNo);
            dingR.setBusinessType(processType);
            dingR.setStaffId(staffId);
            dingR.setResult(resultDTO.getApprovedResult());
            dingR.setInstanceStatus(resultDTO.getInstanceStatus());
            //如果不是运行中则更改业务状态
            if (resultDTO.getInstanceStatus().equals("COMPLETED")) {
                //-1:作废；0待部门审核；1部门驳回；2待财务审核；3财务驳回；4通过
                String redisNode = RedisUtil.getJedisVal(processRedisKey + formUuid + ":" + instanceId + "_" + businessNo);
                Integer status = 4;
                if (!resultDTO.getApprovedResult().equals("agree")) {
                    if (redisNode == null || redisNode.equals("")) {
                        status = 1;
                    } else {
                        status = 3;
                    }
                    if (processType == 5) {
                        status = 5;
                    }
                }
                this.erpNotice(processType, businessNo, staffId, status, remark, instanceId);
            } else if (resultDTO.getInstanceStatus().equals("TERMINATED")) {
                int status = -1;
                if (processType == 5) {
                    status = 5;
                }
                this.erpNotice(processType, businessNo, staffId, status, remark, instanceId);

            } else {
                this.erpNotice(processType, businessNo, staffId, -1, remark, instanceId);

            }
            RedisUtil.delJedis(processRedisKey + formUuid + ":" + instanceId + "_" + businessNo);
            dingProcessRecordsService.save(dingR);
        } catch (Exception e) {
            return RT.error();
        }
        return RT.ok();
    }

    private YidaOperationRecordsResultDTO.ResultBean lastRecords(YidaOperationRecordsResultDTO recordsResultDTO) {
        YidaOperationRecordsResultDTO.ResultBean result = recordsResultDTO.getResult().get(recordsResultDTO.getResult().size() - 1);
        if (result.getActionExit().equals("carbon")) {
            result = recordsResultDTO.getResult().get(recordsResultDTO.getResult().size() - 2);
        }
        return result;
    }

    private void erpNotice(Integer processType, String businessNo, String staffId, Integer status, String remark, String instanceId) {
        YdApproveFactory factory = approveEventHandle.factory(ApproveConstant.yidaProcessAndApproveTypeRoute.get(processType));
        if (factory != null) {
            factory.updateStatus(processType, businessNo, instanceId, status, remark, staffId);
        }
    }

    @Data
    public static class DingCallbackBody {
        private Integer type;//对应枚举类中定义的业务类型
        private String instanceId; //钉钉流程的实例id
        private String status;//对应钉钉表单的审批状态
        private String result;//对应钉钉表单的审批结果
        private String staffId;//钉钉审批人
        private Integer node;//对应系统中成功时的状态
    }

    @Autowired
    private BDingTalkService bDingTalkService;

//    @Autowired
//    private BAdminInfoService bAdminInfoService;

    /**
     * 钉钉审批 连接器状态通知
     *
     * @param body 参数
     * @return 返回给连接器
     */
    @ResponseBody
    @PostMapping("/dingCallback")
    public RT dingCallback(@RequestBody DingCallbackBody body) {
        Integer type = body.getType();
        String instanceId = body.getInstanceId();
        String status = body.status;
        String result = body.result;
        String staffId = body.staffId;
        Integer node = body.getNode();

        BDingTalkDTO dto = bDingTalkService.getByInstanceIdAndType(instanceId, type);
        if (dto == null) {
            return RT.error("实例未找到！");
        }
//        BAdminInfoDO admin = bAdminInfoService.AdminByRUserId(staffId);
//        if (admin == null) {
//            return RT.error("审批人未找到！");
//        }

        try {
            Integer sysStatus = node;
            //进行中
            if (status.equals("TERMINATED")) {
                //撤销
                sysStatus = -1;
            } else {
                if (result != null && result.equals("refuse")) {
                    //此处可优化成灵活配置
                    if (type == 6) {
                        sysStatus = DingFromConstants.dingProcessSysStatusJoin.get(node);
                    }
                }else{
                    //若节点为-5  则跳过不更新
                    if (node == -5)
                        return RT.ok();
                }
            }

            // 获取Service的Class对象
            Class<?> serviceClass = Class.forName("com.d.business.ding.impl.DingApproveServiceImpl");
            DingApproveService service = (DingApproveService) serviceClass.getDeclaredConstructor().newInstance();
            Method processMethod = serviceClass.getMethod("updateStatus", Integer.class,String.class, Integer.class, Integer.class, String.class);
            // 调用方法,-审批人根据业务获取
            Integer mresult = (Integer) processMethod.invoke(service,type, dto.getSourceId(), sysStatus, 1, 2);

            DingProcessRecordsDO dingR = new DingProcessRecordsDO();
            dingR.setInstanceId(instanceId);
            dingR.setCreatedTime(new Date());
            dingR.setFinishTime(new Date());
            dingR.setBusinessNo(dto.getId() + "");
            dingR.setBusinessType(type);
            dingR.setStaffId(staffId);
            dingR.setResult(result);
            dingR.setInstanceStatus(status);
            //如果不是运行中则更改业务状态
            dingProcessRecordsService.save(dingR);
        } catch (Exception e) {
            return RT.error();
        }
        return RT.ok();
    }

}
